package org.xutils.http.utils;

import android.os.Environment;
import android.os.StatFs;
import android.text.TextUtils;
import android.util.Log;

import org.xutils.http.common.util.LogUtil;
import org.xutils.http.xHttp;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * Created by ZZH on 4/20/21.
 *
 * @Date: 4/20/21
 * @Email: zzh_hz@126.com
 * @QQ: 1299234582
 * @Author: zzh
 * @Description:
 */
public class IOUtils {
    public static boolean deleteFileOrDir(File path) {
        if (path == null || !path.exists()) {
            return true;
        }
        if (path.isFile()) {
            return path.delete();
        }
        File[] files = path.listFiles();
        if (files != null) {
            for (File file : files) {
                deleteFileOrDir(file);
            }
        }
        return path.delete();
    }

    public static File getCacheDir(String dirName) {
        File result = null;
        if (isDiskAvailable()) {
            File cacheDir = xHttp.app().getExternalCacheDir();
            if (cacheDir != null) {
                result = new File(cacheDir, dirName);
            }
        }
        if (result == null) {
            result = new File(xHttp.app().getCacheDir(), dirName);
        }
        if (result.exists() || result.mkdirs()) {
            return result;
        } else {
            return null;
        }
    }

    /**
     * 检查磁盘空间是否大于10mb
     *
     * @return true 大于
     */
    public static boolean isDiskAvailable() {
        long size = getDiskAvailableSize();
        return size > 10 * 1024 * 1024L; // > 10bm
    }

    /**
     * 获取磁盘可用空间
     *
     * @return byte
     */
    public static long getDiskAvailableSize() {
        if (!existsSdcard()) return 0;
        File path = Environment.getExternalStorageDirectory(); // 取得sdcard文件路径
        StatFs stat = new StatFs(path.getAbsolutePath());
        long blockSize = 0;
        long availableBlocks = 0;
        blockSize = stat.getBlockSizeLong();
        availableBlocks = stat.getAvailableBlocksLong();
        return availableBlocks * blockSize;
    }

    public static Boolean existsSdcard() {
        return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
    }

    public static long getFileOrDirSize(File file) {
        if (!file.exists()) return 0;
        if (!file.isDirectory()) return file.length();

        long length = 0;
        File[] list = file.listFiles();
        if (list != null) { // 文件夹被删除时, 子文件正在被写入, 文件属性异常返回null.
            for (File item : list) {
                length += getFileOrDirSize(item);
            }
        }

        return length;
    }


    private static final char[] hexDigits =
            {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    public static String toHexString(byte[] bytes) {
        if (bytes == null) return "";
        StringBuilder hex = new StringBuilder(bytes.length * 2);
        for (byte b : bytes) {
            hex.append(hexDigits[(b >> 4) & 0x0F]);
            hex.append(hexDigits[b & 0x0F]);
        }
        return hex.toString();
    }

    public static String md5(String string) {
        byte[] encodeBytes = null;
        try {
            encodeBytes = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException neverHappened) {
            throw new RuntimeException(neverHappened);
        }

        return toHexString(encodeBytes);
    }

    /**
     * 判断是否是图片格式，需要注意的是，判断的是文件路径中是否包含文件扩展名
     * 例：
     * <a href="https://www.zzh.com/asdfasdf.jpg/file.txt">文件</a> 这是一个文本文件，
     * 但是url里面包含.jpg字符串。会判断成是图片。但是有些图片访问需要权限，
     * 例如 <a href="https://www.zzh.com/asdfasdf.jpg/file.txt?token=1234qwe&amp;userId=rewq4321">文件权限</a>
     * 也不能使用判断endWith来判断是否是图片。
     *
     * @param uri 图片路径
     * @return true 是图片
     */
    public static boolean isPicture(String uri) {
        if (TextUtils.isEmpty(uri)) {
            return false;
        }

        return uri.contains(".jpg")
                || uri.contains(".jepg")
                || uri.contains(".png")
                || uri.contains(".bmp")
                || uri.contains(".gif")
                || uri.contains(".tif")
                || uri.contains(".raw")
                || uri.contains(".ico")
                || uri.contains(".webp")
                || uri.contains(".JPG")
                || uri.contains(".JEPG")
                || uri.contains(".PNG")
                || uri.contains(".BMP")
                || uri.contains(".GIF")
                || uri.contains(".TIF")
                || uri.contains(".RAW")
                || uri.contains(".ICO")
                || uri.contains(".WEBP")
                ;
    }

    public static boolean isVideo(String uri) {
        if (TextUtils.isEmpty(uri)) {
            return false;
        }

        return uri.contains(".mp4")
                || uri.contains(".mpeg")
                || uri.contains(".rmvb")
                || uri.contains(".rm")
                || uri.contains(".3gp")
                || uri.contains(".avi")
                || uri.contains(".mov")
                || uri.contains(".wmv")
                || uri.contains(".m4v")
                || uri.contains(".flv")
                || uri.contains(".f4v")
                || uri.contains(".mkv")
                || uri.contains(".MP4")
                || uri.contains(".RMVB")
                || uri.contains(".MPEG")
                || uri.contains(".RM")
                || uri.contains(".3GP")
                || uri.contains(".AVI")
                || uri.contains(".MOV")
                || uri.contains(".WMV")
                || uri.contains(".M4V")
                || uri.contains(".FLV")
                || uri.contains(".F4V")
                || uri.contains(".MKV")
                ;
    }

    /**
     * 输入流转到输出流
     *
     * @param in  输入流
     * @param out 输出流
     * @throws IOException IO异常
     */
    public static void write(InputStream in, OutputStream out) throws IOException {
        if (in == null || out == null) {
            return;
        }
        byte[] buffer = new byte[4096];
        int len = -1;
        while ((len = in.read(buffer)) > 0) {
            out.write(buffer, 0, len);
        }
    }
}
